﻿using System;
using System.Data;
using System.Data.SqlClient;
using System.Security.Principal;
using System.Threading;
using System.Net;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using System.Web;
using System.Web.Mail;
using System.Web.Caching;
using System.Web.SessionState;
using System.IO;
//using System.Messaging;
using HodhodNews;
using Googler.DAL;
using System.Linq;
using System.Collections.Generic;
using HodhodNews.Aggregation;
using Googler.BLL;

namespace Googler.Web
{
    /// <summary>
    /// Summary description for Global.
    /// </summary>
    public class Global : System.Web.HttpApplication
    {
        // private const string DummyPageUrl = "http://localhost/TestCacheTimeout/WebForm1.aspx";
        // private const string CONNECTION_STRING = "Data Source=(local);Initial Catalog=tempdb;Integrated Security=SSPI;";
        // private const string MSMQ_NAME = ".\\private$\\ASPNETService";

        // private const string LOG_FILE = @"c:\temp\Cachecallback.txt";
        private const string DummyCacheItemKey = "GagaGuguGigi";

        public static ArrayList _JobQueue = new ArrayList();
       // public static Timer timer = new Timer(new TimerCallback(DoAggregate));
        public static DateTime AppStartedAt;
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        public Global()
        {
            InitializeComponent();
        }

        protected void Application_BeginRequest(Object sender, EventArgs e)
        {
            // If the dummy page is hit, then it means we want to add another item
            // in cache
            if (HttpContext.Current.Request.Url.ToString().ToLower() == Consts.DummyPageUrl.ToLower())
            {
                // Add the item in cache and when succesful, do the work.
                RegisterCacheEntry();
            }
        }

        protected void Application_Start(Object sender, EventArgs e)
        {
            RegisterCacheEntry();
            SetPageHitterTimer(10);
            Global.AppStartedAt = DateTime.Now;
            Sessions.AppStartedAt = DateTime.Now;

        }

        /// <summary>
        /// Register a cache entry which expires in 1 minute and gives us a callback.
        /// </summary>
        /// <returns></returns>
        private void RegisterCacheEntry()
        {
            // Prevent duplicate key addition
            if (null != HttpContext.Current.Cache[DummyCacheItemKey]) return;

            HttpContext.Current.Cache.Add(DummyCacheItemKey, "Test", null, DateTime.MaxValue,
                TimeSpan.FromMinutes(1), CacheItemPriority.NotRemovable,
                new CacheItemRemovedCallback(CacheItemRemovedCallback));
        }

        /// <summary>
        /// Callback method which gets invoked whenever the cache entry expires.
        /// We can do our "service" works here.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="reason"></param>
        public void CacheItemRemovedCallback(
            string key,
            object value,
            CacheItemRemovedReason reason
            )
        {
            Debug.WriteLine("Cache item callback: " + DateTime.Now.ToString());

            // Do the service works
            DoWork();

            // We need to register another cache item which will expire again in one
            // minute. However, as this callback occurs without any HttpContext, we do not
            // have access to HttpContext and thus cannot access the Cache object. The
            // only way we can access HttpContext is when a request is being processed which
            // means a webpage is hit. So, we need to simulate a web page hit and then 
            // add the cache item.

           // HitPage();
        }

        /// <summary>
        /// Hits a local webpage in order to add another expiring item in cache
        /// </summary>
        private void HitPage()
        {
            //try
            //{
            //    Sessions.NotificationMessages.Add(new NotificationMessage()
            //    {
            //        Text = "Trying to hit page " + Consts.DummyPageUrl + " at " + DateTime.Now
            //    });

            //    WebClient client = new WebClient();
            //    client.DownloadData(Consts.DummyPageUrl);
            //    DoSomeLoggingStuff();
            //}
            //catch (Exception ex)
            //{
            //    Sessions.NotificationMessages.Add(new NotificationMessage()
            //    {
            //        Sender = ex,
            //        Text = ex.Message
            //    });
            //}
        }

        private static void DoAggregate(object state)
        {
            Sessions.NotificationMessages.Add(new NotificationMessage()
            {
                Text = "Timer fired aggregation command at " + DateTime.Now
            });

            //WebClient client = new WebClient();
            //client.DownloadData(Consts.AggregatePageUrl);
        }


        private void SetPageHitterTimer(int minutes)
        {
            //start after 1 minute, fire every {supplied} minutes
            //timer.Change(60 * 1000, minutes * 60 * 1000);
        }


        /// <summary>
        /// Asynchronously do the 'service' works
        /// </summary>
        private void DoWork()
        {
            Debug.WriteLine("Begin DoWork...");
            Debug.WriteLine("Running as: " + WindowsIdentity.GetCurrent().Name);

            //DoSomeLoggingStuff();
            //DoSomeDatabaseOperation();
            //DoSomeEmailSendStuff();
            //DoSomeMSMQStuff();
            //ExecuteQueuedJobs();

            Debug.WriteLine("End DoWork...");
        }


        /// <summary>
        /// Test file write. Make sure the path allows ASPNET or NETWORK SERVICE account
        /// to write 
        /// </summary>
        private void DoSomeLoggingStuff()
        {
            Debug.WriteLine("Writing to file...");

            try
            {


                using (StreamWriter writer = new StreamWriter(Consts.SimulationServiceLogFilePath, true))
                {
                    writer.WriteLine("last self-hitting request from: {0}", DateTime.Now);
                    writer.Close();
                }
            }
            catch (Exception x)
            {
                Debug.WriteLine(x);
            }

            Debug.WriteLine("File write successful");
        }

        /// <summary>
        /// Test database connectivity
        /// </summary>
        private void DoSomeDatabaseOperation()
        {
            //Debug.WriteLine("Connecting to database...");

            //using (SqlConnection con = new SqlConnection(CONNECTION_STRING))
            //{
            //    con.Open();

            //    using (SqlCommand cmd = new SqlCommand("INSERT INTO ASPNETServiceLog VALUES (@Message, @DateTime)", con))
            //    {
            //        cmd.Parameters.Add("@Message", SqlDbType.VarChar, 1024).Value = "Hi I'm the ASP NET Service";
            //        cmd.Parameters.Add("@DateTime", SqlDbType.DateTime).Value = DateTime.Now;

            //        cmd.ExecuteNonQuery();
            //    }

            //    con.Close();
            //}

            //Debug.WriteLine("Database connection successful");
        }

        /// <summary>
        /// Test email send
        /// </summary>
        private void DoSomeEmailSendStuff()
        {
            try
            {
                MailMessage msg = new MailMessage();
                msg.From = "abc@cde.fgh";
                msg.To = "ijk@lmn.opq";
                msg.Subject = "Reminder: " + DateTime.Now.ToString();
                msg.Body = "This is a server generated message";

                SmtpMail.Send(msg);
            }
            catch (Exception x)
            {
                Debug.WriteLine(x);
            }
        }

        /// <summary>
        /// Test MSMQ
        /// </summary>
        private void DoSomeMSMQStuff()
        {
            //using (MessageQueue queue = new MessageQueue(MSMQ_NAME))
            //{
            //    queue.Send(DateTime.Now);
            //    queue.Close();
            //}
        }

        protected void Session_Start(Object sender, EventArgs e)
        {

        }


        protected void Application_EndRequest(Object sender, EventArgs e)
        {

        }

        protected void Application_AuthenticateRequest(Object sender, EventArgs e)
        {

        }

        protected void Application_Error(Object sender, EventArgs e)
        {
            Debug.WriteLine(Server.GetLastError());
        }

        protected void Session_End(Object sender, EventArgs e)
        {

        }

        protected void Application_End(Object sender, EventArgs e)
        {

        }

        #region Web Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
        }
        #endregion
    }
}

